package com.example.wac.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.wac.entity.User;
import com.example.wac.mapper.UserMapper;
import com.example.wac.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.stream.IntStream;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author wac
 * @since 2022-01-05
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    ThreadPoolTaskExecutor executor;

    @Override
    public List<User> list(int shardTotalCount, int shardItem) {
        List<User> list = this.baseMapper.list(shardTotalCount, shardItem);
        return list;
    }

    @Override
    public List<User> asyncGetList() {
        List<User> list = new LambdaQueryChainWrapper<>(this.baseMapper).list();
        List<User> resultList = new CopyOnWriteArrayList<>();
        int count = executor.getCorePoolSize() + (list.size() % executor.getCorePoolSize() == 0 ? 0 : 1);
        int index = list.size() / executor.getCorePoolSize();
        // [0, count - 1]
        IntStream.rangeClosed(0,count - 1).forEach(i -> {
            int start = i * index;
            int end = Math.min(start + index, list.size());
            executor.execute(() -> {
                List<User> userList = list.subList(start, end);
                userList.stream().forEach( user -> {
                    user.setName(user.getName() + "[已经过处理]");
                    resultList.add(user);
                });
            });
        });
        executor.shutdown();
        try {
            // 保证所有线程执行完并将所有对象装进list
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return resultList;
    }

    @Override
    public List<User> countDownLatchGetList() {
        List<User> list = new LambdaQueryChainWrapper<>(this.baseMapper).list();
        List<User> resultList = new CopyOnWriteArrayList<>();
        int count = executor.getCorePoolSize() + (list.size() % executor.getCorePoolSize() == 0 ? 0 : 1);
        int index = list.size() / executor.getCorePoolSize();
        CountDownLatch countDownLatch = new CountDownLatch(count);
        IntStream.rangeClosed(0,count - 1).forEach(i -> {
            int start = i * index;
            int end = Math.min(start + index, list.size());
            executor.execute(() -> {
                List<User> userList = list.subList(start, end);
                userList.stream().forEach( user -> {
                    user.setName(user.getName() + "[已经过处理]");
                    resultList.add(user);
                });
                countDownLatch.countDown();
            });
        });
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return resultList;
    }

    @Override
    public List<User> semaphoreList() {
        List<User> list = new LambdaQueryChainWrapper<>(this.baseMapper).list();
        List<User> resultList = new CopyOnWriteArrayList<>();
        int count = executor.getCorePoolSize() + (list.size() % executor.getCorePoolSize() == 0 ? 0 : 1);
        int index = list.size() / executor.getCorePoolSize();
        IntStream.rangeClosed(0,count - 1).forEach(i -> {
            int start = i * index;
            int end = Math.min(start + index, list.size());
            executor.execute(() -> {
                List<User> userList = list.subList(start, end);
                userList.stream().forEach( user -> {
                    user.setName(user.getName() + "[已经过处理]");
                    resultList.add(user);
                });
            });
        });
        // semaphore不具有等待线程结束的特点
        return resultList;
    }


}
